package tools.kmer;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.PriorityQueue;

public class kmerUtils {
	private static HashMap<String, String> methodsHelp= new HashMap<String, String>();
	private final static String sep="\t";
//	private final static String[] nucleotides= new String[]{"A","C","G","T","N"};
	
	
	public static void main(String[] args)throws Exception{
		//load helpMap
		methodsHelp.put("mergeKmers", "mergeKmers - merge several files containing kmers\n\targs = <kmer file 1> ... <kmer file n> <outfile>\n");
		
		if(args.length>0){
			if(args[0].equals("mergeKmers")&&args.length>2){
				ArrayList<String> files= new ArrayList<String>();
				for(int i=1;i<args.length-1;++i){
					files.add(args[i]);
				}
				mergeKmers(files,args[args.length-1]);
			}else if(args[0].equals("method2")&&args.length>1){
				
			}else{
				System.err.println(printHelp(args[0]));
			}
		}else{
			System.err.println(printHelp());
		}
	}
	
	private static String printHelp(){
		String help="";
		for (String s : methodsHelp.values()) {
			help+=s;
		}
		
		return help;
	}
	
	private static String printHelp(String method){
		if(methodsHelp.containsKey(method)){
			return methodsHelp.get(method);
		}
		return printHelp();
	}
	
	private static void mergeKmers(ArrayList<String> files,String outfile)throws Exception{
		mergeKmers_kmer kmer,nextkmer;
		mergeKmers_kmerSortObj kmerSort;
		PriorityQueue<mergeKmers_kmerSortObj> sortedList= new PriorityQueue<mergeKmers_kmerSortObj>();
		BufferedWriter out= new BufferedWriter(new FileWriter(outfile));
		int result;

		for(String file : files){
			kmerSort=new mergeKmers_kmerSortObj(file);
			if(kmerSort.hasMore()){
				sortedList.add(kmerSort);
			}
		}
		
		kmerSort=sortedList.peek();
		kmer=new mergeKmers_kmer(kmerSort.getCurKmer().getKmer(),0);
		
		while(sortedList.size()>0){
			kmerSort=sortedList.poll();
			nextkmer=kmerSort.getCurKmer();
			if((result=kmer.compareTo(nextkmer))<=0){
				if(result==0){
					//merge
					kmer.add(nextkmer.getCount());
				}else{
					//print
					out.write(kmer+"\n");
					kmer=nextkmer;
				}
				kmerSort.next();
				if(kmerSort.hasMore()){
					sortedList.add(kmerSort);
				}
			}else{
				throw new Exception("False sorting");
			}
		}
		out.write(kmer+"\n");
		out.close();
	}
}

class mergeKmers_kmerSortObj implements Comparable<mergeKmers_kmerSortObj>{

	private String nextLine;
	private mergeKmers_kmer curKmer;
	private BufferedReader in;
	private boolean hasMore;
	
	protected mergeKmers_kmerSortObj(String file)throws Exception{
		in= new BufferedReader(new FileReader(file));
		hasMore=readNext();
	}
	
	protected mergeKmers_kmer getCurKmer() {
		return curKmer;
	}

	protected boolean hasMore() {
		return hasMore;
	}

	protected void next()throws Exception{
		hasMore=readNext();
	}

	private boolean readNext()throws Exception{
		nextLine=in.readLine();
		if(nextLine==null){
			return false;
		}
		curKmer= new mergeKmers_kmer(nextLine);
		return true;
	}
	
	public String toString(){
		return curKmer.toString();
	}
	
	@Override
	public int compareTo(mergeKmers_kmerSortObj o) {
		return this.curKmer.compareTo(o.curKmer);
	}
	
}

class mergeKmers_kmer implements Comparable<mergeKmers_kmer>{

	private String kmer;
	private int count;
	
	protected mergeKmers_kmer(String line){
		final String[] l= line.split("\t");
		kmer=l[1];
		count=Integer.parseInt(l[0]);
	}
	
	protected mergeKmers_kmer(String kmer,int count){
		this.kmer=kmer;
		this.count=count;
	}
	
	
	
	protected String getKmer() {
		return kmer;
	}

	protected int getCount() {
		return count;
	}

	protected mergeKmers_kmer(mergeKmers_kmer o){
		this(o.kmer,o.count);
	}
	
	protected void add(int n){
		count+=n;
	}
	
	public String toString(){
		return count+"\t"+kmer;
	}
	
	@Override
	public int compareTo(mergeKmers_kmer o) {
		return this.kmer.compareTo(o.kmer);
	}
	
}
